import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {Observable} from 'rxjs';
import {catchError} from 'rxjs/operators';
import {environment} from '../../../environments/environment';
import {BASE_HTTP_OPTIONS, baseHandleError, ReturnForm} from '@sb/base';
import {ShowMenus} from '../entity/show-menu';
import {Route, Router, Routes} from '@angular/router';
import {Error404Component} from '../error404/error404.component';
import {LoginGuard} from './login.guard';

@Injectable({
    providedIn: 'root'
})
export class MenuService {

    private menuUrl = environment.baseServerUrl + 'menu';

    private cacheResult: string = null;

    constructor(private http: HttpClient,
                private router: Router) {
    }

    /**
     * 尝试登录
     */
    getShowMenu(): Observable<ReturnForm<ShowMenus>> {
        return new Observable<ReturnForm<ShowMenus>>(
            (subscriber): void => {
                if (this.cacheResult) {
                    subscriber.next(JSON.parse(this.cacheResult));
                    subscriber.complete();
                } else {
                    this.http.post<ReturnForm<ShowMenus>>(`${this.menuUrl}/getShowMenu`, null, BASE_HTTP_OPTIONS)
                        .pipe(
                            catchError(baseHandleError<ReturnForm<ShowMenus>>('getShowMenu'))
                        ).subscribe(returnForm => {
                        if (returnForm.success) {
                            const menus = returnForm.message;

                            // 设置路由
                            const routes = this.getRoutes(menus);

                            const oldRouter = this.router.config;
                            oldRouter[0].children = routes;
                            const route: Route = oldRouter[oldRouter.length - 1];
                            route.component = Error404Component;

                            const oneRoutes = this.getOneRoutes(menus);
                            if (oneRoutes.length > 0) {
                                oneRoutes.splice(0, 0, {path: '', redirectTo: routes[0].path, pathMatch: 'full'});
                            }
                            oneRoutes.push({path: '**', component: Error404Component});
                            oldRouter[1].children = oneRoutes;


                            const url = this.router.url;
                            this.router.resetConfig(oldRouter);

                            this.router.navigateByUrl(url);

                            this.cacheResult = JSON.stringify(returnForm);
                            subscriber.next(returnForm);
                            subscriber.complete();
                        }
                    });
                }
            });
    }

    /**
     * 更新菜单
     * @param menus 显示菜单
     * @param parentPath 路由路径（相对于index）
     */
    updateMenus(menus: ShowMenus, parentPath = '') {
        for (let i = 0; i < menus.length; i++) {
            const menu = menus[i];
            if (!menu) {
                continue;
            }
            let exist = false;
            for (const c of this.router.config) {
                exist = c.path === menu.code;
                if (exist) {
                    break;
                }
            }
            if (!exist) {
                if (menu.urlType === 'ABSOLUTE') {
                    let routerLink;
                    if (menu.openType === 'OPEN') {
                        routerLink = '/one/' + menu.code;
                    } else {
                        routerLink = parentPath + '/' + menu.code;
                    }
                    menu.routerLink = routerLink;
                    menu.loadChildren = 'src/app/main/redirect/redirect.module#RedirectModule';
                } else {
                    let tempParentPath = parentPath;
                    if (menu.openType === 'OPEN') {
                        tempParentPath = '';
                    }
                    menu.routerLink = tempParentPath + '/' + menu.code;
                    if (menu.loadChildren) {
                        if (menu.children && menu.children.length > 0) {
                            const arr = [];
                            for (const subMenu of menu.children) {
                                arr.push({
                                    name: subMenu.name,
                                    code: menu.code + '/' + subMenu.code,
                                    routerLink: menu.routerLink + '/' + subMenu.code
                                });
                            }
                            menus.splice(i, 1, ...arr);
                            i += arr.length - 1;
                        }
                    } else if (menu.children && menu.children.length > 0) {
                        this.updateMenus(menu.children, menu.routerLink);
                    }
                }
            }
        }
    }

    clearCache() {
        this.cacheResult = null;
    }

    private getRoutes(menus: ShowMenus): Routes {
        if (!menus) {
            return [];
        }
        // 测试嵌套路由
        const routes: Routes = [];
        for (let i = 0; i < menus.length; i++) {
            const menu = menus[i];
            if (!menu) {
                continue;
            }
            if (menu.urlType === 'ABSOLUTE') {
                const route = {
                    path: menu.code,
                    loadChildren: 'src/app/main/redirect/redirect.module#RedirectModule',
                    data: {breadcrumb: menu.name, link: menu.loadChildren, permissions: menu.permissions},
                    canActivate: [LoginGuard]
                };
                routes.push(route);
            } else {
                if (menu.loadChildren) {
                    const s = menu.loadChildren.split('|');
                    const t = s[0].indexOf('>');
                    let v = null;
                    if (t > 0) {
                        v = s[0].substring(t + 1);
                        s[0] = s[0].substring(0, t);
                    }

                    const route: Route = {
                        path: menu.code,
                        loadChildren: s[0],
                        data: {breadcrumb: menu.name, permissions: menu.permissions},
                        canActivate: [LoginGuard],
                    };

                    // 修改 code 地址
                    if (v) {
                        menu.code += '/' + v;
                    }

                    if (s.length > 1) {
                        const params = s[1].split('&');
                        const obj = {};
                        for (const p of params) {
                            const temp = p.trim().split('=');
                            if (temp.length > 1) {
                                obj[temp[0]] = temp[1];
                            }
                        }
                        route.data.param = obj;
                    }
                    routes.push(route);
                } else if (menu.children && menu.children.length > 0) {
                    const childRoutes = this.getRoutes(menu.children);
                    if (childRoutes.length > 0) {
                        routes.push({
                            path: menu.code,
                            children: childRoutes,
                            data: {breadcrumb: menu.name},
                            canActivate: [LoginGuard],
                        });
                    }
                }
            }
        }
        if (routes.length > 0) {
            routes.splice(0, 0, {path: '', redirectTo: routes[0].path, pathMatch: 'full'});
            routes.push({path: '**', component: Error404Component});
        }
        return routes;
    }

    private getOneRoutes(menus: ShowMenus): Routes {
        if (!menus) {
            return [];
        }
        const routes: Routes = []; // 测试嵌套路由
        for (let i = 0; i < menus.length; i++) {
            const menu = menus[i];
            if (!menu) {
                continue;
            }
            if (menu.urlType === 'ABSOLUTE') {
                const route = {
                    path: menu.code,
                    loadChildren: 'src/app/main/redirect/redirect.module#RedirectModule',
                    data: {
                        breadcrumb: menu.name,
                        link: menu.loadChildren,
                        permissions: menu.permissions,
                        showBack: menu.openType === 'OPEN'
                    },
                    canLoad: [LoginGuard]
                };
                routes.push(route);
            } else {
                if (menu.loadChildren) {
                    const s = menu.loadChildren.split('|');
                    const t = s[0].indexOf('>');
                    if (t > 0) {
                        s[0] = s[0].substring(0, t);
                    }
                    const route: Route = {
                        path: menu.code,
                        loadChildren: menu.loadChildren,
                        data: {
                            breadcrumb: menu.name,
                            permissions: menu.permissions
                        },
                        canLoad: [LoginGuard],
                    };
                    if (s.length > 1) {

                        const params = s[1].split('&');
                        const obj = {};
                        for (const p of params) {
                            const temp = p.trim().split('=');
                            if (temp.length > 1) {
                                obj[temp[0]] = temp[1];
                            }
                        }
                        route.data.param = obj;
                    }
                    routes.push(route);
                } else if (menu.children && menu.children.length > 0) {
                    routes.push(...this.getOneRoutes(menu.children));
                }
            }
        }
        return routes;
    }
}
